package com.xrtn.utils;

import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.imaging.jpeg.JpegProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.exif.ExifIFD0Directory;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.web.multipart.MultipartFile;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import javax.imageio.ImageIO;

public class ImageUtil {
    public static Map<String, Object> dealPothoWithInputStream(MultipartFile imageFile) throws IOException{
        Map<String,Object> returnMap = new HashMap<>();

        Map<String,Object> params = new HashMap<>();

        String fileName = imageFile.getOriginalFilename();
        String formatName = fileName.substring(fileName.lastIndexOf(".") + 1);

        InputStream input = imageFile.getInputStream();
        BufferedImage bufImg = ImageIO.read(input); // 把图片读入到内存中

        int angle = 0;
        if ("jpg".equals(formatName.toLowerCase()) || "jpeg".equals(formatName.toLowerCase()))  {
            angle = ImageUtil.getRotateAngleForPhotoInputStream(imageFile.getInputStream());
            InputStream againInput = imageFile.getInputStream(); // 旋转的时候会关闭inputStream，所以需要再获取一次
            if (angle != 0) {
                bufImg = ImageUtil.rotatePhonePhoto(againInput, angle);
            }
        }

        if(imageFile.getSize() > 800 * 1024){
            // 压缩代码
            bufImg = Thumbnails.of(bufImg).width(1200).outputQuality(0.9).asBufferedImage();
        }

        int width = ObjUtils.isNotEmpty(bufImg.getWidth()) ? bufImg.getWidth() : 900;
        int height = ObjUtils.isNotEmpty(bufImg.getHeight()) ? bufImg.getHeight() : 900;

        params.put("width", width);
        params.put("height", height);

        returnMap.put("params", params);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();// 存储图片文件byte数组


        if ("png".equals(formatName.toLowerCase()))  {
            BufferedImage to = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = to.createGraphics();
            to = g2d.getDeviceConfiguration().createCompatibleImage(width, height,
                    Transparency.TRANSLUCENT);
            g2d.dispose();
            g2d = to.createGraphics();
            @SuppressWarnings("static-access")
            Image from = bufImg.getScaledInstance(width, height, bufImg.SCALE_AREA_AVERAGING);
            g2d.drawImage(from, 0, 0, null);
            g2d.dispose();
            ImageIO.write(to, formatName, bos); // 图片写入到 ImageOutputStream
        } else {
            ImageIO.write(bufImg, formatName, bos); // 图片写入到 ImageOutputStream
        }

        input = new ByteArrayInputStream(bos.toByteArray());

        returnMap.put("input", input);

        return returnMap;
    }

    /**
     * 裁剪PNG图片工具类
     *
     * @param fromFile
     *            源文件
     * @param toFile
     *            裁剪后的文件
     * @param outputWidth
     *            裁剪宽度
     * @param outputHeight
     *            裁剪高度
     * @param proportion
     *            是否是等比缩放
     */
    public static void resizePng(File fromFile, File toFile, int outputWidth, int outputHeight,
                                 boolean proportion) {
        try {
            BufferedImage bi2 = ImageIO.read(fromFile);
            int newWidth;
            int newHeight;
            // 判断是否是等比缩放
            if (proportion) {
                // 为等比缩放计算输出的图片宽度及高度
                double rate1 = ((double) bi2.getWidth(null)) / (double) outputWidth + 0.1;
                double rate2 = ((double) bi2.getHeight(null)) / (double) outputHeight + 0.1;
                // 根据缩放比率大的进行缩放控制
                double rate = rate1 < rate2 ? rate1 : rate2;
                newWidth = (int) (((double) bi2.getWidth(null)) / rate);
                newHeight = (int) (((double) bi2.getHeight(null)) / rate);
            } else {
                newWidth = outputWidth; // 输出的图片宽度
                newHeight = outputHeight; // 输出的图片高度
            }
            BufferedImage to = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = to.createGraphics();
            to = g2d.getDeviceConfiguration().createCompatibleImage(newWidth, newHeight,
                    Transparency.TRANSLUCENT);
            g2d.dispose();
            g2d = to.createGraphics();
            @SuppressWarnings("static-access")
            Image from = bi2.getScaledInstance(newWidth, newHeight, bi2.SCALE_AREA_AVERAGING);
            g2d.drawImage(from, 0, 0, null);
            g2d.dispose();
            ImageIO.write(to, "png", toFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static int getRotateAngleForPhotoInputStream(InputStream is) {
        int angle = 0;
        try {
            Metadata metadata = JpegMetadataReader.readMetadata(is);
            Directory directory = metadata.getDirectory(ExifIFD0Directory.class);
            if (directory.containsTag(274)) {
                int orientation = directory.getInt(274);

                if (6 == orientation) {
                    angle = 90;
                } else if (3 == orientation) {
                    angle = 180;
                } else if (8 == orientation) {
                    angle = 270;
                }
            }
        } catch (JpegProcessingException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return angle;
    }

    public static int getRotateAngleForPhoto(String filePath) {
        File file = new File(filePath);
        int angle = 0;
        try {
            FileInputStream fis = new FileInputStream(file);

            angle = getRotateAngleForPhotoInputStream(fis);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return angle;
    }

    public static BufferedImage rotatePhonePhoto(InputStream inputStream, int angel) {
        BufferedImage res = null;
        try {
            BufferedImage src = ImageIO.read(inputStream);

            int src_width = src.getWidth();
            int src_height = src.getHeight();

            Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);

            res = new BufferedImage(rect_des.width, rect_des.height, 1);
            Graphics2D g2 = res.createGraphics();

            g2.translate((rect_des.width - src_width) / 2,
                    (rect_des.height - src_height) / 2);
            g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);

            g2.drawImage(src, null, null);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return res;
    }

    public static Rectangle CalcRotatedSize(Rectangle src, int angel) {
        if (angel >= 90) {
            if (angel / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel %= 90;
        }

        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2.0D;
        double len = 2.0D * Math.sin(Math.toRadians(angel) / 2.0D) * r;
        double angel_alpha = (3.141592653589793D - Math.toRadians(angel)) / 2.0D;
        double angel_dalta_width = Math.atan(src.height / src.width);
        double angel_dalta_height = Math.atan(src.width / src.height);

        int len_dalta_width = (int) (len * Math.cos(3.141592653589793D - angel_alpha -
                angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(3.141592653589793D - angel_alpha -
                angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new Rectangle(new Dimension(des_width, des_height));
    }

    public static void main(String[] args) {
//    int angle = getRotateAngleForPhoto("/Users/pingping/Downloads/20180612144421_9757.jpg");
//    rotatePhonePhoto("/Users/pingping/Downloads/20180612144421_9757.jpg_bak", angle);
//    System.out.print("angle" + angle);
    }
}